import { Select } from 'antd'
import { useEffect, useMemo, useRef, useState } from 'react'
import './style/textareaWithParams.less'

// 解析富文本内容为保存格式
function parseToValue(input, optionsMap) {
  const tempDiv = document.createElement('div')
  tempDiv.innerHTML = input.replace(
    /<span[^>]*?>(.*?)<\/span>/g, // 匹配所有 <span> 标签
    (match, content) => {
      // 在对象中查找匹配的 key
      const key = Object.keys(optionsMap).find(k => optionsMap[k] === content)
      return key ? `{{#${key}#}}` : content // 如果找到 key，返回 key，否则保持原内容
    }
  )

  // 遍历子节点，将 <br> 转换为 \n，同时处理文本内容
  const traverseNodes = node => {
    let result = ''
    node.childNodes.forEach(child => {
      if (child.nodeName === 'BR') {
        result += '\n' // 换行符
      } else if (child.nodeType === Node.TEXT_NODE) {
        result += child.textContent // 文本内容
      } else if (child.nodeType === Node.ELEMENT_NODE) {
        result += traverseNodes(child) // 递归解析子元素
      }
    })
    return result
  }
  return traverseNodes(tempDiv)
}

export default function TextareaWithParams({
  placeholder = '',
  value,
  error = false,
  children = null,
  onUpload = undefined,
  onChange,
  onVarEvent = undefined,
  citeOptions
}) {
  const { textareaRef, handleFocus, handleBlur } = usePlaceholder(placeholder)
  const valueRef = useRef(value || '')
  const selectVarRef = useRef(null)

  const [showVarList, setShowVarList] = useState(false)

  const optionsMap = useMemo(() => {
    return citeOptions.reduce((acc, item) => {
      item.options.forEach(option => {
        const [_keyPart, valuePart] = option.value.split(',')
        const newKey = `${item.key}.${valuePart}`
        const newValue = `${item.label}/${option.label}`
        acc[newKey] = newValue
      })
      return acc
    }, {})
  }, [citeOptions])

  // 校验变量是否可用
  const validateVarAvailble = () => {
    const value = valueRef.current
    const [html, error] = parseToHTML(value || '', true)
    textareaRef.current.innerHTML = html
    return error
  }

  // useEffect(() => {
  //   onVarEvent && onVarEvent(validateVarAvailble)
  //   return () => onVarEvent && onVarEvent(() => {})
  // }, [flowNode])

  const handleInput = () => {
    const value = parseToValue(textareaRef.current.innerHTML, optionsMap)
    valueRef.current = value
    onChange(value)
  }

  const isVarInFlow = part => {
    console.log('citeOptions', part, citeOptions)
    return false
  }
  function parseToHTML(input, validate = false) {
    let error = false
    const html = input
      .replace(/{{#(.*?)#}}/g, (a, part) => {
        // // 判断变量是否存在flow中
        if (validate) {
          error = isVarInFlow(part)
        }
        const msgZh = optionsMap?.[part] || part
        return `<span class=${error ? 'textarea-error' : 'textarea-badge'} contentEditable="false">${msgZh}</span>`
      })
      .replace(/\n/g, '<br>')
    return [html, error]
  }

  useEffect(() => {
    console.log('TextareaWithParams useEffect value :>> ', value)
    textareaRef.current.innerHTML = parseToHTML(value || '')[0]
    handleBlur()
  }, [])

  // 在光标位置插入内容
  function handleInsertVariable(item, _option) {
    console.log('handleInsertVariable', item, _option)
    if (!item) {
      return
    }
    setShowVarList(false)
    handleFocus()

    const selection = window.getSelection()
    let range = selection.getRangeAt(0)
    if (!selection.rangeCount) return

    if (!textareaRef.current.contains(range.commonAncestorContainer)) {
      range = document.createRange()
      range.selectNodeContents(textareaRef.current) // 设置范围为富文本框内容
      range.collapse(false) // 将光标定位到内容末尾
      selection.removeAllRanges()
      selection.addRange(range)
    }

    // 文本框内容
    const infos = item.split(',')
    // const key = `${infos[0]}.${infos[1]}`
    let label = infos[1]
    for (let i = 0; i < citeOptions.length; i++) {
      if (citeOptions[i].key === infos[0]) {
        label = `${citeOptions[i].label}/${infos[1]}`
        break
      }
    }

    const html = `<span class="textarea-badge" contentEditable="false">${label}</span>`
    const fragment = range.createContextualFragment(html)

    const lastChild = fragment.lastChild // 提前保存引用
    if (lastChild) {
      range.deleteContents()
      range.insertNode(fragment)

      // 现在用保存的引用而不是 fragment.lastChild
      range.setStartAfter(lastChild)
      range.setEndAfter(lastChild)
      selection.removeAllRanges()
      selection.addRange(range)
    } else {
      console.warn('No valid child nodes to insert.')
    }

    handleInput()
  }

  const handlePaste = e => {
    e.preventDefault() // 阻止默认粘贴行为
    const text = e.clipboardData.getData('text') // 从剪贴板中获取纯文本内容
    document.execCommand('insertText', false, text)
  }

  return (
    <div
      className={`text-area-with-params-container nodrag relative flex w-full flex-col rounded-md border text-sm shadow-sm ${
        error ? 'border-red-500' : 'border-input'
      }`}
    >
      <div
        className="flex items-center justify-between gap-1 border-b px-2 py-1"
        // onClick={() => textareaRef.current.focus()}
      >
        <span className="left-text-prompt">变量输入</span>
        <div className="flex gap-2">
          <Select
            ref={selectVarRef}
            open={showVarList}
            style={{ width: 120 }}
            onSelect={handleInsertVariable}
            onFocus={() => {
              setShowVarList(true)
            }}
            onBlur={() => {
              setShowVarList(false)
            }}
            placement={'bottomRight'}
            className={'text-area-with-params-select'}
            popupClassName={'text-area-with-params-popup'}
            options={citeOptions}
          />
        </div>
      </div>
      <div
        ref={textareaRef}
        contentEditable
        style={{ height: 100 }}
        onInput={handleInput}
        onPaste={handlePaste}
        onFocus={handleFocus}
        onBlur={handleBlur}
        onKeyDown={e => {
          // 唤起插入变量
          if (e.key === '{') {
            setShowVarList(true)
            e.preventDefault()
          }
        }}
        className="nowheel panel-custom-richtext max-h-64 min-h-[80px] overflow-y-auto overflow-x-hidden whitespace-pre-line rounded-md border-none px-3 py-2 outline-none placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50 dark:text-gray-50"
      ></div>
      {children}
    </div>
  )
}

function usePlaceholder(placeholder) {
  const divRef = useRef(null)

  const handleFocus = () => {
    if (divRef.current && divRef.current.innerHTML.trim() === placeholder) {
      divRef.current.innerHTML = ''
      divRef.current.classList.remove('placeholder')
    }
  }

  const handleBlur = () => {
    if (divRef.current && ['<br>', ''].includes(divRef.current.innerHTML.trim())) {
      divRef.current.innerHTML = placeholder
      divRef.current.classList.add('placeholder')
    }
  }

  useEffect(() => {
    if (!placeholder) return
    if (divRef.current) {
      // 添加事件监听
      divRef.current.addEventListener('focus', handleFocus)
      divRef.current.addEventListener('blur', handleBlur)

      // 清理事件监听
      return () => {
        if (divRef.current) {
          divRef.current.removeEventListener('focus', handleFocus)
          divRef.current.removeEventListener('blur', handleBlur)
        }
      }
    }
  }, [placeholder])

  return { textareaRef: divRef, handleFocus, handleBlur }
}
